package com.drg.center.config;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.guaike.core.entity.constant.HttpHeaderConstant;
import com.guaike.core.entity.enums.ErrorCodeEnum;
import com.guaike.core.entity.enums.UserAccTypeEnum;
import com.guaike.core.entity.exception.ApiException;
import com.guaike.core.entity.result.User;
import com.guaike.core.redis.helper.LoginHelper;
import com.guaike.core.web.helper.RequestSignHelper;
import com.guaike.core.web.utils.SpecialRequestUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RSet;
import org.redisson.api.RedissonClient;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.*;

@Slf4j
public class AuthorityFilter implements Filter {


    private RedissonClient redissonClient;

    private String env;

    public void setEnv(String env) {
        this.env = env;
    }

    public void setRedissonClient(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }

    private static final String[] WHITE_URLS = new String[]{"/doc.html", "/webjars/bycdao-ui", "/swagger-resources", "/v2/api-docs"};

    @SneakyThrows
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;

        // 特殊请求
        if (SpecialRequestUtil.canIgnoreDocCheck(request, env)) {
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }

        String url = request.getRequestURI();
        String[] var6 = WHITE_URLS;
        int var7 = var6.length;
        String uri;
        for (int var8 = 0; var8 < var7; ++var8) {
            uri = var6[var8];
            if (url.contains(uri)) {
                filterChain.doFilter(servletRequest, servletResponse);
                return;
            }
        }
        String accessToken = request.getHeader(HttpHeaderConstant.HEADER_NAME_TOKEN);
        User user = StringUtils.isNotBlank(accessToken)? LoginHelper.getUserFromCache(this.redissonClient, accessToken): null;
        servletRequest.setAttribute(HttpHeaderConstant.HEADER_NAME_USERID, user !=null? user.getUserId(): null);
        if (RequestSignHelper.isNoLogin(url)) {
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }

        String contentType = request.getHeader("Content-Type");
        if (StringUtils.isBlank(contentType) || contentType.contains("multipart/form-data")) {
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }

        if (Objects.isNull(user)) {
            throw new ApiException(ErrorCodeEnum.ERROR_SYS_INVALID_TOKEN.getCode(), ErrorCodeEnum.ERROR_SYS_INVALID_TOKEN.getDesc());
        } else if (user.getAccType().equals(UserAccTypeEnum.SYS_MANAGER.getType())) {
            filterChain.doFilter(servletRequest, servletResponse);
        } else {
            RSet<String> rset = this.redissonClient.getSet("button_urls");
            if (CollectionUtils.isNotEmpty(rset) && rset.contains(url)) {
                Set<String> btnUrls = user.getBtnUrls();
                if(CollectionUtils.isNotEmpty(btnUrls)&&btnUrls.contains(url)){
                    filterChain.doFilter(servletRequest, servletResponse);
                }else {
                    throw new ApiException(ErrorCodeEnum.ERROR_BIZ_NO_PERMISSION_OPERATE.getCode(), ErrorCodeEnum.ERROR_BIZ_NO_PERMISSION_OPERATE.getDesc());
                }
            } else {
                filterChain.doFilter(servletRequest, servletResponse);
            }
        }

    }


    /**
     * 判断是否为json字符串
     */
    private boolean isJson(String body) {
        return body.startsWith("{") || body.startsWith("[");
    }

    /**
     * 获取post请求参数
     */
    private String getBodys(String body) {
        JSONObject jsonObject = new JSONObject(Maps.newLinkedHashMap());

        if (StringUtils.isBlank(body)) {
            return jsonObject.toJSONString();
        }
        if (isJson(body)) {
            return body;
        }

        try {
            set2JsonObject(body, jsonObject);
        } catch (UnsupportedEncodingException e) {
            log.error(">>>URL Decoder时发生异常！", e);
        }

        return jsonObject.toJSONString();
    }

    /**
     * 获取get请求参数
     */
    private String getParams(HttpServletRequest request) {
        JSONObject jsonObject = new JSONObject(Maps.newLinkedHashMap());
        String query = request.getQueryString();
        log.info(">>>query: {}", query);

        if (StringUtils.isBlank(query)) {
            return jsonObject.toJSONString();
        }

        try {
            set2JsonObject(query, jsonObject);
        } catch (UnsupportedEncodingException e) {
            log.error(">>>URL Decoder时发生异常！", e);
        }

        return jsonObject.toJSONString();
    }

    private void set2JsonObject(String text, JSONObject jsonObject) throws UnsupportedEncodingException {
        TreeMap<String, Object> treeMap = new TreeMap<>();
        String[] params = text.split("&");
        for (String param : params) {
            String[] keyValue = param.split("=", 2);
            if (keyValue.length > 1) {
                treeMap.put(keyValue[0], URLDecoder.decode(keyValue[1], "UTF-8"));
            } else {
                treeMap.put(keyValue[0], "");
            }
        }
        Iterator<Map.Entry<String, Object>> iterator = treeMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Object> entry = iterator.next();
            jsonObject.put(entry.getKey(), entry.getValue());
        }
    }



}
